import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { PriceChart } from "@/components/market/chart"; import { EventRow } from "@/components/market/event-row"; import { InstrumentHeader } from "@/components/market/instrument-header"; import { InstrumentStats } from "@/components/market/instrument-stats"; import { CoverageBadge } from "@/components/market/coverage-badge"; import { ProvenancePanel } from "@/components/market/provenance-panel"; import { RightsBadge, StatusBadge } from "@/components/ui/status-badge"; import { Empty, Kv, Section } from "@/components/ui/section"; import { api, apiOptional } from "@/lib/api"; import { ASSET_CLASS_LABEL, formatDateTime, instrumentHref } from "@/lib/format"; import type { Exchange, Filing, Instrument, InstrumentCoverage, MarketEvent, Quote } from "@/lib/types"; export const dynamic = "force-dynamic"; interface Detail { instrument: Instrument; company: { id: string; name: string; cik: string | null; country: string | null; sector: string | null; industry: string | null; website: string | null } | null; exchange: (Exchange & { status: NonNullable }) | null; quote: Quote | null; aliases: Array<{ alias: string; source_id: string | null }>; sources: string[]; related: Instrument[]; } async function load(id: string) { return api(`/v1/instruments/${encodeURIComponent(id)}`); } export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise { const { id } = await params; try { const d = await load(id); const i = d.instrument; const title = `${i.symbol} · ${i.name}`; const desc = `${i.name} (${i.symbol}) — ${ASSET_CLASS_LABEL[i.asset_class] ?? i.asset_class}${d.exchange ? ` on ${d.exchange.name}` : ""}. Canonical price, sources, confidence, history and events on Market Atlas.`; return { title, description: desc, alternates: { canonical: instrumentHref(i.id) }, openGraph: { title, description: desc, type: "website" } }; } catch { return { title: "Instrument" }; } } export default async function InstrumentPage({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; const d = await load(id); if (!d?.instrument) notFound(); const i = d.instrument; const [events, filings, coverage] = await Promise.all([ apiOptional(`/v1/events?instrument=${encodeURIComponent(i.id)}&limit=25`), d.company?.cik ? apiOptional(`/v1/filings?cik=${encodeURIComponent(d.company.cik)}&limit=15`) : Promise.resolve(null), apiOptional(`/v1/coverage/${encodeURIComponent(i.id)}`), ]); const isRate = i.asset_class === "TREASURY" || i.asset_class === "INTEREST_RATE" || i.asset_class === "BOND"; const jsonLd = { "@context": "https://schema.org", "@type": "FinancialProduct", name: i.name, tickerSymbol: i.symbol, category: ASSET_CLASS_LABEL[i.asset_class] ?? i.asset_class, url: `${process.env.NEXT_PUBLIC_SITE_URL ?? "https://www.market-atlas.co"}${instrumentHref(i.id)}`, ...(d.exchange ? { provider: { "@type": "Organization", name: d.exchange.name } } : {}), }; return (